package com.ponhu.ea2.stockcenter.provider.service.rpc.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ponhu.ea2.common.basic.model.ResponseBean;
import com.ponhu.ea2.ordercenter.facade.bms.PlatformOrderFacade;
import com.ponhu.ea2.ordercenter.model.enums.PlatformOrderStatusEnum;
import com.ponhu.ea2.ordercenter.model.vo.bms.platform.SimpleOrderDTO;
import com.ponhu.ea2.scmcenter.facade.bms.stock.StockCenterApiFacade;
import com.ponhu.ea2.scmcenter.model.vo.stock.OutWarehouseDetailVo;
import com.ponhu.ea2.stockcenter.enums.DefinedSystem;
import com.ponhu.ea2.stockcenter.enums.ResponseCodeEnum;
import com.ponhu.ea2.stockcenter.provider.constants.CommonConstant;
import com.ponhu.ea2.stockcenter.provider.entity.StockInventoryDocOccupy;
import com.ponhu.ea2.stockcenter.provider.mapper.StockInventoryRealMapper;
import com.ponhu.ea2.stockcenter.provider.service.biz.stocksales.SalesLevelStockResponseService;
import com.ponhu.ea2.stockcenter.provider.service.entity.StockInventoryDocOccupyService;
import com.ponhu.ea2.stockcenter.provider.support.enums.DocOccupyStatusEnum;
import com.ponhu.ea2.stockcenter.provider.support.enums.StockChangeInnerEventEnum;
import com.ponhu.ea2.stockcenter.provider.support.exception.StockRuntimeException;
import com.ponhu.ea2.stockcenter.provider.utils.DingTalkHandler;
import com.ponhu.ea2.stockcenter.service.bms.StockFixService;
import com.ponhu.ea2.stockcenter.vo.ReturnResponseBean;
import com.ponhu.ea2.stockcenter.vo.StockFixResultVO;
import io.netty.util.concurrent.FastThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.ponhu.ea2.stockcenter.enums.ResponseCodeEnum.JOIN_OMS_GET_ORDER_STATUS_LIST_EXCEPTION_900701;
import static com.ponhu.ea2.stockcenter.enums.ResponseCodeEnum.PARAMS_INCORRECT_EXCEPTION_900003;

/**
 * @author Wang
 * @date 2022/1/18 3:42 下午
 */
@Slf4j
@DubboService(version = "1.0.0", interfaceClass = StockFixService.class, timeout = 60000)
public class StockFixServiceImpl implements StockFixService {

    //需要被修复的销售单货品编码列表
    private static final FastThreadLocal<List<String>> fixedInventoriesThreadLocal = new FastThreadLocal<>();
    //需要被修复的采退单货品编码列表
    private static final FastThreadLocal<List<String>> fixedPurchaseThreadLocal = new FastThreadLocal<>();

    @Resource
    private StockInventoryDocOccupyService docOccupyService;
    @Resource
    private DingTalkHandler dingTalkHandler;
    @Resource
    private SalesLevelStockResponseService salesLevelStockResponseService;
    @Resource
    private StockInventoryRealMapper stockInventoryRealMapper;

    @DubboReference(version = "1.0.0", check = false)
    private PlatformOrderFacade platformOrderFacade;
    @DubboReference(version = "1.0.0", check = false, timeout = 60000)
    private StockCenterApiFacade stockCenterApiFacade;


    /**
     * 全量修复销售订单状态（取消占用、销售出库状态）
     * @return
     */
    @Override
    public ReturnResponseBean<List<StockFixResultVO>> fixAllInventoryDocOccupyData() {
        //获取所有下单占用状态的记录
        List<StockInventoryDocOccupy> docOccupyList = docOccupyService.list(Wrappers.lambdaQuery(StockInventoryDocOccupy.class)
                .eq(StockInventoryDocOccupy::getDocType, DefinedSystem.OMS.ordinal())
                .eq(StockInventoryDocOccupy::getStatus, DocOccupyStatusEnum.PLACED.getCode()));
        if (CollectionUtils.isEmpty(docOccupyList)) {
            log.info("订单占用数据修复-订单占用记录为空，无需要修复");
            return null;
        }
        //组装订单号
        List<String> collect = docOccupyList.stream().map(StockInventoryDocOccupy::getDocNo).distinct().collect(Collectors.toList());
        log.info("订单占用数据修复-已下单订单数量:{}", collect.size());

        List<StockFixResultVO> resultVOList = this.fixInventoryDocOccupyData(collect);

        //修复销售层-占用数
        if(fixedInventoriesThreadLocal.get() != null && fixedInventoriesThreadLocal.get().size() > 0){
            log.info("订单占用数据修复-货品编码数量:{}", fixedInventoriesThreadLocal.get().size());
            stockInventoryRealMapper.updateSalesUsedStockNum(fixedInventoriesThreadLocal.get());
        }

        //清空ThreadLocal数据
        removeThreadLocalData();
        return ReturnResponseBean.ok(resultVOList);
    }

    @Override
    public ReturnResponseBean<List<StockFixResultVO>> fixAllPurchaseDocOccupyData() {
        //获取所有下单占用状态的记录
        List<StockInventoryDocOccupy> docOccupyList = docOccupyService.list(Wrappers.lambdaQuery(StockInventoryDocOccupy.class)
                .eq(StockInventoryDocOccupy::getDocType, DefinedSystem.PURCHASE_CENTER.ordinal())
                .eq(StockInventoryDocOccupy::getStatus, DocOccupyStatusEnum.PLACED.getCode()));
        if (CollectionUtils.isEmpty(docOccupyList)) {
            log.info("采退单占用数据修复-采退单占用记录为空，无需要修复");
            return null;
        }
        //组装订单号
        List<String> collect = docOccupyList.stream().map(StockInventoryDocOccupy::getDocNo).distinct().collect(Collectors.toList());
        log.info("采退单占用数据修复-已占用采退单数量:{}", collect.size());

        List<StockFixResultVO> resultVOList = this.fixPurchaseDocOccupyData(collect);

        //修复销售层-占用数
        if(fixedPurchaseThreadLocal.get() != null && fixedPurchaseThreadLocal.get().size() > 0){
            log.info("采退占用数据修复-货品编码数量:{}", fixedPurchaseThreadLocal.get().size());
            stockInventoryRealMapper.updateSalesUsedStockNum(fixedPurchaseThreadLocal.get());
        }

        //清空ThreadLocal数据
        removePurchaseThreadLocalData();
        return ReturnResponseBean.ok(resultVOList);
    }

    private List<StockFixResultVO> fixPurchaseDocOccupyData(List<String> docNoList) {
        if (CollectionUtils.isEmpty(docNoList)) {
            throw new StockRuntimeException(PARAMS_INCORRECT_EXCEPTION_900003.getCode(), "采退单列表不能为空");
        }

        //查询"已下单"状态数据
        List<StockInventoryDocOccupy> docOccupyList = docOccupyService.list(
                Wrappers.lambdaQuery(StockInventoryDocOccupy.class)
                        .eq(StockInventoryDocOccupy::getDocType, DefinedSystem.PURCHASE_CENTER.ordinal())
                        .eq(StockInventoryDocOccupy::getStatus, DocOccupyStatusEnum.PLACED.getCode())
                        .in(StockInventoryDocOccupy::getDocNo, docNoList)
        );

        if (CollectionUtils.isEmpty(docOccupyList)) {

            return docNoList.stream().map(docNo ->
                    new StockFixResultVO().setDocNo(docNo).setContent("无需修复")).collect(Collectors.toList());
        }
        List<String> collect = docOccupyList.stream().map(StockInventoryDocOccupy::getDocNo).collect(Collectors.toList());

        //获取OMS订单状态数据
        ResponseBean<List<OutWarehouseDetailVo>> responseBean = stockCenterApiFacade.queryOutWarehouseStatus(collect);
        log.info("获取采购单状态数据: {}", JSONObject.toJSONString(responseBean));

        if (responseBean.getCode() != ResponseCodeEnum.SUCCESS.getCode()) {
            //异常发钉钉提醒
            dingTalkHandler.sendMsg(String.format("采退占用数据修复-获取采购单状态数据异常%s", JSONObject.toJSONString(responseBean)), null);
            log.error("采退单占用数据修复-获取采购单状态数据异常, {}", responseBean);

            throw new StockRuntimeException(JOIN_OMS_GET_ORDER_STATUS_LIST_EXCEPTION_900701.getCode(), responseBean.getMsg());
        }

        //采退单列表为空，不需要修复数据
        if (CollectionUtils.isEmpty(responseBean.getData())) {
            return docNoList.stream().map(docNo ->
                    new StockFixResultVO().setDocNo(docNo).setContent("无需修复")).collect(Collectors.toList());
        }

        List<StockFixResultVO> fixResultVOList = new ArrayList<>();
        responseBean.getData().forEach(warehouseDetailVo -> {
            StockInventoryDocOccupy docOccupy = docOccupyList.stream().filter(f -> f.getDocNo().equals(warehouseDetailVo.getProcurementReturnOrderNo())).findFirst().orElse(null);

            if (docOccupy != null) {
                //采退出库
                if (warehouseDetailVo.getReturnOrderStatus() == CommonConstant.PURCHASE_STATUS.FINISHED) {
                    //添加货品编码
                    if(fixedPurchaseThreadLocal.get() == null){
                        fixedPurchaseThreadLocal.set(new ArrayList<>());
                    }
                    fixedPurchaseThreadLocal.get().add(docOccupy.getInventoryCode());

                    //修改状态-采退出库
                    docOccupyService.takeDocRecordSalesOut(docOccupy.getDocNo(), StockChangeInnerEventEnum.PURCHASE_RETURN_OUT_OF_SYSTEM_FIX);
                } else if (warehouseDetailVo.getReturnOrderStatus() == CommonConstant.PURCHASE_STATUS.CLOSED) {
                    //添加货品编码
                    if(fixedPurchaseThreadLocal.get() == null){
                        fixedPurchaseThreadLocal.set(new ArrayList<>());
                    }
                    fixedPurchaseThreadLocal.get().add(docOccupy.getInventoryCode());

                    //修改状态-采退出库
                    docOccupyService.takeDocRecordSalesOut(docOccupy.getDocNo(), StockChangeInnerEventEnum.PURCHASE_RETURN_CANCEL_OF_SYSTEM_FIX);
                }else {
                    fixResultVOList.add(new StockFixResultVO().setDocNo(warehouseDetailVo.getProcurementReturnOrderNo()).setContent("无需修复"));
                }
            } else {
                fixResultVOList.add(new StockFixResultVO().setDocNo(warehouseDetailVo.getProcurementReturnOrderNo()).setContent("无需修复"));
            }
        });

        return fixResultVOList;
    }

    private void removeThreadLocalData() {
        fixedInventoriesThreadLocal.remove();

    }

    private void removePurchaseThreadLocalData() {
        fixedPurchaseThreadLocal.remove();

    }

    /**
     * 修复销售订单占用数据
     *
     * @param docNoList
     * @return
     */
    private List<StockFixResultVO> fixInventoryDocOccupyData(List<String> docNoList) {
        if (CollectionUtils.isEmpty(docNoList)) {
            throw new StockRuntimeException(PARAMS_INCORRECT_EXCEPTION_900003.getCode(), "订单列表不能为空");
        }

        //查询"已下单"状态数据
        List<StockInventoryDocOccupy> docOccupyList = docOccupyService.list(
                Wrappers.lambdaQuery(StockInventoryDocOccupy.class)
                        .eq(StockInventoryDocOccupy::getDocType, DefinedSystem.OMS.ordinal())
                        .eq(StockInventoryDocOccupy::getStatus, DocOccupyStatusEnum.PLACED.getCode())
                        .in(StockInventoryDocOccupy::getDocNo, docNoList)
        );

        if (CollectionUtils.isEmpty(docOccupyList)) {

            return docNoList.stream().map(docNo ->
                    new StockFixResultVO().setDocNo(docNo).setContent("无需修复")).collect(Collectors.toList());
        }
        List<String> collect = docOccupyList.stream().map(StockInventoryDocOccupy::getDocNo).collect(Collectors.toList());

        //获取OMS订单状态数据
        ResponseBean<List<SimpleOrderDTO>> responseBean = platformOrderFacade.getSimpleOrderLsit(String.join(",", collect));

        if (responseBean.getCode() != ResponseCodeEnum.SUCCESS.getCode()) {
            //异常发钉钉提醒
            dingTalkHandler.sendMsg(String.format("订单占用数据修复-获取OMS订单状态数据异常%s", JSONObject.toJSONString(responseBean)), null);
            log.error("订单占用数据修复-获取OMS订单状态数据异常, {}", responseBean);

            throw new StockRuntimeException(JOIN_OMS_GET_ORDER_STATUS_LIST_EXCEPTION_900701.getCode(), responseBean.getMsg());
        }

        //订单列表为空，不需要修复数据
        if (CollectionUtils.isEmpty(responseBean.getData())) {
            return docNoList.stream().map(docNo ->
                    new StockFixResultVO().setDocNo(docNo).setContent("无需修复")).collect(Collectors.toList());
        }

        List<StockFixResultVO> fixResultVOList = new ArrayList<>();
        responseBean.getData().forEach(simpleOrderDTO -> {
            StockInventoryDocOccupy docOccupy = docOccupyList.stream().filter(f -> f.getDocNo().equals(simpleOrderDTO.getId())).findFirst().orElse(null);

            if (docOccupy != null) {
                //销售出库
                if (simpleOrderDTO.getOrderStatus() == PlatformOrderStatusEnum.ORDER_COMPLETE_SHIPMENTS_SUM.getCode() ||
                        simpleOrderDTO.getOrderStatus() == PlatformOrderStatusEnum.ORDER_SUCCESS_SUM.getCode()) {
                    //走销售出库

                    //添加货品编码
                    if(fixedInventoriesThreadLocal.get() == null){
                        fixedInventoriesThreadLocal.set(new ArrayList<>());
                    }
                    fixedInventoriesThreadLocal.get().add(docOccupy.getInventoryCode());

                    //修改状态-销售出库
                    docOccupyService.takeDocRecordSalesOut(docOccupy.getDocNo(), StockChangeInnerEventEnum.SALES_OUT_OF_SYSTEM_FIX);
                }
                //交易关闭、异常订单
                else if (simpleOrderDTO.getOrderStatus() == PlatformOrderStatusEnum.ORDER_CANCEL_SUM.getCode() ||
                        simpleOrderDTO.getOrderStatus() == PlatformOrderStatusEnum.ORDER_RETURN_SUM.getCode() ||
                        simpleOrderDTO.getOrderStatus() == PlatformOrderStatusEnum.ORDER_EXCEPTION_SUM.getCode()) {

                    //添加货品编码
                    if(fixedInventoriesThreadLocal.get() == null){
                        fixedInventoriesThreadLocal.set(new ArrayList<>());
                    }
                    fixedInventoriesThreadLocal.get().add(docOccupy.getInventoryCode());

                    //取消订单占用
                    docOccupyService.cancelDocOccupy(docOccupy.getDocNo(), StockChangeInnerEventEnum.CANCEL_SALES_ORDER);
                } else {
                    fixResultVOList.add(new StockFixResultVO().setDocNo(simpleOrderDTO.getId()).setContent("无需修复"));
                }
            } else {
                fixResultVOList.add(new StockFixResultVO().setDocNo(simpleOrderDTO.getId()).setContent("无需修复"));
            }
        });

        return fixResultVOList;
    }

    /**
     * 修复库存-占用数
     *
     * @param inventoryCodeList
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<StockFixResultVO> fixSalesUsedStockNum(List<String> inventoryCodeList) {
        if (CollectionUtils.isEmpty(inventoryCodeList)) {
            return null;
        }

        //根据货品编码查找销售订单记录
        List<StockInventoryDocOccupy> docOccupyList = docOccupyService.list(
                Wrappers.lambdaQuery(StockInventoryDocOccupy.class)
                        .eq(StockInventoryDocOccupy::getDocType, DefinedSystem.OMS.ordinal())
                        .eq(StockInventoryDocOccupy::getStatus, DocOccupyStatusEnum.PLACED.getCode())
                        .in(StockInventoryDocOccupy::getInventoryCode, inventoryCodeList)
        );

        List<StockFixResultVO> result = null;
        if (CollectionUtils.isNotEmpty(docOccupyList)) {
            //修复订单状态数据（取消占用，销售出库异常订单）
            log.info("修复销售层占用数-修复销售单状态 start. 订单数量：{}", docOccupyList.size());
            List<String> collect = docOccupyList.stream().map(StockInventoryDocOccupy::getDocNo).distinct().collect(Collectors.toList());
            result = this.fixInventoryDocOccupyData(collect);
            log.info("修复销售层占用数-修复销售单状态 end.");
        }

        //修复销售层-占用数
        log.info("修复销售层占用数-修复占用数 start. 货品编码数量：{}", inventoryCodeList.size());
        stockInventoryRealMapper.updateSalesUsedStockNum(inventoryCodeList);
        log.info("修复销售层占用数-修复占用数 end.");
        return result;
    }
}
